/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "main_functions.h"
#include "board.h"
#include "bflb_uart.h"

#include "lv_conf.h"
#include "lvgl.h"
#include "lv_port_disp.h"
#include "lv_port_indev.h"
#include "log.h"

#include <FreeRTOS.h>
#include <task.h>
#include "timers.h"



/// Global Destructor for C++, which we're not using.
/// See https://alex-robenko.gitbook.io/bare_metal_cpp/compiler_output/static#custom-destructors
void *__dso_handle = NULL;

lv_obj_t * result = NULL;
static void lv_task(void *pvParameters){
    LOG_E("###: lv handler\r\n");
    while(1){
        lv_task_handler();
        vTaskDelay(20);
    }
    vTaskDelete(NULL);
}

void lv_log_print_g_cb(const char *buf)
{
    printf("[LVGL] %s", buf);
}

lv_obj_t * screen=NULL;

static lv_obj_t * canvas;
// 1位索引色缓冲区（28x28像素，784位=98字节）
static uint8_t canvas_buffer[280 * 280/8]; 
static uint8_t digit_array[28][28]; // 28x28 数组

// 添加全局触摸事件回调来调试
static void touch_event_debug_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_indev_t * indev = lv_event_get_indev(e);
    
    lv_point_t point;
    lv_indev_get_point(indev, &point);
    printf("Touch Event touch_event_debug_cb : code=%d, pos=(%d, %d)\n", code, point.x, point.y);
}

lv_coord_t lastX=-1;
lv_coord_t lastY=-1;
lv_draw_line_dsc_t line_dsc;
static lv_color_t palette[2];


// 绘制点到画布和数组（适配1位索引色）
void draw_point(int x, int y, int size)
{
    
    // 将坐标转换为28x28范围内的坐标（除以放大倍数10）
    int canvas_x = x / 10;
    int canvas_y = y / 10;
    
    if(canvas_x >= 0 && canvas_x < 28 && canvas_y >= 0 && canvas_y < 28) {
        // 绘制笔画（周围扩展区域增加宽度）
        for(int i = -size; i <= size; i++) {
            for(int j = -size; j <= size; j++) {
                int px = canvas_x + i;
                int py = canvas_y + j;
                
                if(px >= 0 && px < 28 && py >= 0 && py < 28) {
                    // 更新数组（1表示黑色）
                    digit_array[py][px] = 1;
                }
            }
        }
    }
}

void dawPoint(lv_coord_t x ,lv_coord_t y,int size){
    draw_point(x,y,1);
    int bb=size/2;
    for(int xx=x-bb;xx<x+bb;xx++){
        for(int yy=y-bb;yy<y+bb;yy++){
            lv_canvas_set_px(canvas, xx, yy, palette[1]);
        }
    }
    
}

// 触摸事件处理
static void canvas_event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_indev_t * indev = lv_event_get_indev(e);
    //printf("Touch Event: code=%d, pos=(%d, %d)\n", code, point.x, point.y);
    lv_point_t point;
    lv_indev_get_point(indev, &point);
    
    // 调整坐标（考虑画布位置偏移）
    lv_coord_t x = point.x - lv_obj_get_x(canvas);
    lv_coord_t y = point.y - lv_obj_get_y(canvas);
    //lv_canvas_set_px(canvas, x, y, palette[1]);
    dawPoint(x,y,5);
}

// 清除画布
static void clear_canvas(lv_event_t * e)
{
    printf("------clear_canvas-----\r\n");
    // 清除数组
    for(int i = 0; i < 28; i++) {
        for(int j = 0; j < 28; j++) {
            digit_array[i][j] = 0;
        }
    }
    lastX=-1;
    lastY=-1;
    // 清除画布显示（填充白色背景）
    lv_canvas_fill_bg(canvas, lv_color_white(), LV_OPA_COVER);
}

// 打印数组（调试用）
void print_array(void)
{
    printf("28x28 Array:\n");
    for(int i = 0; i < 28; i++) {
        for(int j = 0; j < 28; j++) {
            printf("%d ", digit_array[i][j]);
        }
        printf("\n");
    }
}

// 识别按钮回调函数
static void recognize_cb(lv_event_t * e)
{
    printf("------recognize_cb-----\r\n");
    char text[20]={0};

    sprintf(text,"recognize....");
    printf(text);
    lv_label_set_text(result, text);
    char num=recg(digit_array);
    sprintf(text,"result:%d",num);
    printf(text);
    lv_label_set_text(result, text);
    // 可在此处添加手写识别逻辑
    //print_array(); // 调试时可开启
}


void init_canvas(void)
{
    // 创建画布
    canvas = lv_canvas_create(lv_scr_act());
    

   // 关键设置：确保画布可以接收和保持输入事件
    lv_obj_add_flag(canvas, LV_OBJ_FLAG_CLICKABLE);
    lv_obj_add_flag(canvas, LV_OBJ_FLAG_GESTURE_BUBBLE); // 允许手势冒泡
    lv_obj_clear_flag(canvas, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_clear_flag(canvas, LV_OBJ_FLAG_SCROLL_ELASTIC);

    lv_obj_set_size(canvas, 280, 280); // 10倍放大显示
    lv_obj_center(canvas);
    
    // 初始化画布缓冲区（使用1位索引色格式）
    lv_canvas_set_buffer(canvas, canvas_buffer, 280, 280, LV_IMG_CF_INDEXED_1BIT);
    
    // 配置1位索引色的调色板（仅支持2种颜色）
 
    palette[0]=lv_color_hex(0xFFFFFF);// 索引0：背景色（白色）
    palette[1]=lv_color_hex(0x0);// 索引1：绘制色（黑色）
    lv_canvas_set_palette(canvas, 0, palette[0]);
    lv_canvas_set_palette(canvas, 1, palette[1]);
    
    // 初始化数组为0（白色背景）
    for(int i = 0; i < 28; i++) {
        for(int j = 0; j < 28; j++) {
            digit_array[i][j] = 0;
        }
    }
    
    // 设置画布为白色背景（填充索引0对应的颜色）
    lv_canvas_fill_bg(canvas, palette[0], LV_OPA_COVER);

     // 为画布添加触摸事件
    lv_obj_add_event_cb(canvas, canvas_event_cb, LV_EVENT_PRESSED , NULL);
    lv_obj_add_event_cb(canvas, canvas_event_cb, LV_EVENT_PRESSING , NULL);
    lv_obj_add_event_cb(canvas, canvas_event_cb, LV_EVENT_CLICKED, NULL);
}


void create_ui(void)
{
   
    // 创建按钮容器
    lv_obj_t * btn_cont = lv_obj_create(lv_scr_act());
    lv_obj_set_size(btn_cont, 280, 60);
    lv_obj_align(btn_cont, LV_ALIGN_BOTTOM_MID, 0, -20);
    lv_obj_set_flex_flow(btn_cont, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(btn_cont, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    
    // 创建识别按钮
    lv_obj_t * recognize_btn = lv_btn_create(btn_cont);
    lv_obj_set_size(recognize_btn, 100, 40);
    lv_obj_t * recognize_label = lv_label_create(recognize_btn);
    lv_label_set_text(recognize_label, "recognize");
    lv_obj_center(recognize_label);
    lv_obj_add_event_cb(recognize_btn, recognize_cb, LV_EVENT_CLICKED, NULL);
    
    // 创建清除按钮
    lv_obj_t * clear_btn = lv_btn_create(btn_cont);
    lv_obj_set_size(clear_btn, 100, 40);
    lv_obj_t * clear_label = lv_label_create(clear_btn);
    lv_label_set_text(clear_label, "clean");
    lv_obj_center(clear_label);
    lv_obj_add_event_cb(clear_btn, clear_canvas, LV_EVENT_CLICKED, NULL);
    
    // 创建标题
    lv_obj_t * title = lv_label_create(lv_scr_act());
    lv_label_set_text(title, "number recognize");
    lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0);
    lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 10);


    // 创建标题
    result = lv_label_create(lv_scr_act());
    lv_label_set_text(result, "result:NULL");
    lv_obj_set_style_text_font(result, &lv_font_montserrat_20, 0);
    lv_obj_align(result, LV_ALIGN_TOP_MID, 0, 30);


   // lv_obj_add_event_cb(lv_scr_act(), touch_event_debug_cb, LV_EVENT_PRESSED | LV_EVENT_PRESSING, NULL);
    

     // 初始化画布
    init_canvas();

   
    
}

int main()
{
    board_init();

    lv_log_register_print_cb(lv_log_print_g_cb);
    lv_init();
    lv_port_disp_init();
    lv_port_indev_init();

    create_ui();
    setup();

    printf("model load successfully!!\r\n");
    xTaskCreate(lv_task, (char *)"lv_task", 2048, NULL, configMAX_PRIORITIES - 2, NULL);
    vTaskStartScheduler();

    while (1) {
        vTaskDelay(20);
    }
}